<?php
/**
 * 单件实例化 PDO, 然后的然后 就不知道了 
 *
 * @filesource DB.class.php
 * @package MagicDB
 * @subpackage 
 * @version $id: 0.1, utf8, Sun Dec 20 21:25:28 CST 2009
 * @author LD King <kldscs[at]gmail.com>
 * @copyright Copyleft (D.) 2007 - 2009 MiFunny China Inc.
 * @link http://mifunny.info/
 * @example 
 * 
 *   $_config['MagicDB'] = array(
 *   	'driver' => 'mysql',  //数据库驱动, 参看 http://www.php.net/manual/en/pdo.drivers.php
 *   	'dsn' => 'mysql:dbname=testdb;host=127.0.0.1;port=3333',
 *   	'username' => 'test', 
 *   	'password' => 'test',
 *   	'charset' => 'utf8',
 *   	'collate' => 'utf8_general_ci',
 *   	'persistent' => true,  //是否使用长连接
 *   	'options' => array(
 *   		PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
 *   		), //额外选项
 *     );
 * 
 *  如果是MySQL, dsn包括 :
 *   	'host' => '127.0.0.1',  //MySQL服务器IP地址
 *   	'port' => '3306',  //端口
 *   	'unix_socket' => '/var/mysql//mysql.sock', 
 *   	'dbname' => 'test', //数据库名
 */
require_once 'spl_autoload.func.php';

class DB {
	private static $_instance;
	
	/**
	 * 数据库对象 (默认PDO)
	 * @var pdo object
	 */
	public $db;
	
	private function __construct(){}
	private function __clone(){}
	
	/**
	 * 获得静态对象实例
	 * 
	 * @return self
	 */
	public static function getInstance(array $default_policy = null){
		if( !(self::$_instance instanceof self) ) {
			if( is_null($default_policy) ) {
				global $_config;
				$policy = $_config['MagicDB'];
			}else{
				$policy = $default_policy;
			}
			
			//preg_match('/^(.*):.*/U', $policy['dsn'], $driver);
			if ( empty($policy) ) {
        		throw new RuntimeException('('.__CLASS__.'->'.__FUNCTION__.')'.
        		  "Error: Someone should give any stuff to \$_config['MagicDB'] !");
        	}
			
        	if( extension_loaded('pdo_'.$policy['driver']) ){
        		self::$_instance->db = self::_initializePDO($policy);
        	}else{
        		if( $policy['driver'] != 'mysql'){
        			throw new LogicException('('.__CLASS__.'->'.__FUNCTION__.')'.
        			  "Error: pdo_{$policy['driver']} initialization failed, check your system configuration !");
        		}else{
        			self::$_instance->db = self::_initializeMagicDB($policy); //MagcicDB
        		}//END mysqli/mysql start
        	}
		}
		return self::$_instance;
	}//END func getInstance
	
	/**
	 * 对付PDO的初始化函数
	 *
	 * @param array $policy 配置数组
	 * 
	 * @return database object
	 */
	private static function _initializePDO($policy){
		//driver_options
		if( $policy['persistent'] ) $options = array(PDO::ATTR_PERSISTENT => true);
		else $options = array();
		
		if( is_array($policy['options']) ){
			$options = array_merge($options, $policy['options']);
		}
		
		$policy['username'] = $policy['username'] ? $policy['username'] : NULL;
		$policy['password'] = $policy['password'] ? $policy['password'] : NULL;
/*		$dns = $policy['driver'] .
		  ( empty($policy['host']) ? '' : ':host='.$policy['host'] ) .
		  ( empty($policy['port']) ? '' : ';port='.$policy['port'] ) .
		  ( empty($policy['dbname']) ? '': ';dbname='.$policy['dbname'] ) .
		  ( empty($policy['unix_socket']) ? '' : ';unix_socket='.$policy['unix_socket'] );*/

		if( $db = new PDO($policy['dsn'], $policy['username'], $policy['password'], $options) ){
			$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC); //setFetchMode fetch模式,关联数组
			if( !empty($policy['charset'])  ){ //字符集
				$charset = "SET NAMES ".$policy['charset'];
				if( !empty($policy['collate']) ){
					$charset .= " COLLATE ".$policy['collate'];
				}
				$db->exec($charset);
			}
			return $db;
		}else{
			throw new RuntimeException('('.__CLASS__.'->'.__FUNCTION__.')'.
			  "Error: connect database failed !");
		}
	}//END func _initializePDO
	
	/**
	 * 初始化非PDO连接对象
	 *
	 * @param array $policy 配置数组
	 * 
	 * @return database object
	 */
	private static function _initializeMagicDB($policy){
		preg_match("/host=(.*?)($| |;)/i",$policy['dsn'],$host);
		preg_match("/port=(.*?)($| |;)/i",$policy['dsn'],$port);
		preg_match("/unix_socket=(.*?)($| |;)/i",$policy['dsn'],$unix_socket);
		preg_match("/dbname=(.*?)($| |;)/i",$policy['dsn'],$dbname);
		$policy['host'] = $host[1] ? $host[1] : NULL;
		$policy['port'] = $port[1] ? $port[1] : NULL;
		$policy['unix_socket'] = $unix_socket[1] ? $unix_socket[1] : NULL;
		$policy['dbname'] = $dbname[1] ? $dbname[1] : NULL; 

		//start MagicDB
		if( extension_loaded('mysqli') ){
        	return new mmysqli($policy);
        }else {
        	return new mmysql($policy);
        }
	}//END func _initializeMagicDB
	
}//END class DB

/**
 * 获得第一行的返回值
 * 
 * @param string $statement SQL语句
 * 
 * @return array 一维数组
 */
function _one($statement){
	try{
		$re = DB::getInstance()->db->query($statement);
		if( is_object($re) ){
			$row = $re->fetch();
			$re->nextRowset();
			return $row;
		}else return false;
	}catch(Exception $err){
        return false; //$err;
    }
}//END func _one

/**
 * 获得所有的返回值
 * 
 * @param string $statement SQL语句
 * 
 * @return array 二维数组
 */
function _all($statement){
	try{
	 	$re = DB::getInstance()->db->query($statement);
		if( is_object($re) ){
			$rows = $re->fetchAll();
			$re->nextRowset();
			return $rows;
		}else return false;
	}catch(Exception $err){
    	return false;
    }
}//END func _all

/**
 * 返回处理过的字符串(用户SQL语句), 防止SQL注入
 *   注: 建议程序开始设置  @set_magic_quotes_runtime(0);
 * 
 * @param mixed $value
 * 
 * @return mixed
 */
function _q($value){
	if(is_string($value)){
		return DB::getInstance()->db->quote($value);
	}else{
		return $value;
	}
}//END _q
?>
